package com.scs.application.core.mvc.controller;

import com.scs.application.core.consts.ErrorCode;
import com.scs.application.core.entity.BaseEntity;
import com.scs.application.core.flow.FlowContext;
import com.scs.application.core.flow.FlowContextHolder;
import com.scs.application.core.mvc.dto.FlowChangeDTO;
import com.scs.application.core.service.IBaseService;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.sys.adapter.FlowAdapter;
import com.scs.application.modules.sys.entity.Flow;
import com.scs.application.modules.sys.entity.FlowButton;
import com.scs.application.modules.sys.model.RestResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
/**
 * @Description： 基类controller-流程
 */
@Slf4j
public class FlowController<S extends IBaseService<E>, E extends BaseEntity> extends CrudController<S, E> {

    @Autowired
    protected FlowAdapter flowAdapter;

    /**
     * 流程节点改变
     *
     * @return
     */
    @PostMapping("/flow_change")
    public final RestResult flowChange(@RequestBody @Valid FlowChangeDTO<E> dto) {

        FlowContext flowContext = FlowContextHolder.currentContext();
        if (StringUtils.isBlank(dto.getBusId())) {
            return RestResult.error(String.format("缺少主键参数"));
        }

        String flowKey = dto.getFlowKey();
        String buttonKey = dto.getButtonKey();
        String entityId = dto.getBusId();
        String comment = dto.getComment();

        Flow flow = flowAdapter.getFlowService(true).findByFlowKey(flowKey);
        if (flow == null) {
            return RestResult.error(String.format("流程%s未定义", flowKey));
        }

        if (flow.getFlagDisable()) {
            return RestResult.error(String.format("流程%s已禁用", flowKey));
        }

        List<FlowButton> buttons = flowAdapter.getFlowButtonService(true).getByFlowId(flow.getId());

        Optional<FlowButton> optionalFlowButton = buttons.stream().filter(b -> b.getCode().equalsIgnoreCase(buttonKey)).findFirst();
        if (!optionalFlowButton.isPresent()) {
            return RestResult.error(String.format("流程按钮%s未定义", buttonKey));
        }
        FlowButton button = optionalFlowButton.get();

        flowContext.setFlow(flow);
        flowContext.setButton(button);
        flowContext.setButtons(buttons);
        flowContext.setBusId(entityId);
        flowContext.setComment(comment);
        flowContext.setAttachmentUrl(dto.getAttachmentUrl());
        flowContext.setSignBase64(dto.getSignBase64());
        flowContext.setBusTable(dto.getBusTable());
        flowContext.setBusIdName(dto.getBusIdName());
        flowContext.setBusTypeName(dto.getBusTypeName());
        flowContext.setFlowStatusTextTo(dto.getFlowStatusTextTo());
        flowContext.setFlowStatusTextFrom(dto.getFlowStatusTextFrom());
        flowContext.setEntityWeb(dto.getEntityWeb());

        try {
            synchronized (entityId.intern()) {
                service.handleFlowChange();

                Object handledResult = flowContext.getHandledResult();
                String handledMsg = flowContext.getHandledMsg();
                return RestResult.ok(StringUtils.defaultIfBlank(handledMsg, "操作成功"), handledResult);
            }
        } finally {
            FlowContextHolder.clear();
        }
    }

    /**
     * 批量流程修改
     */
    @PostMapping("/flow_change_list")
    public final RestResult  flowChangeList(@RequestBody @Valid List<FlowChangeDTO> list) {
        RestResult restResult = RestResult.ok();
        RestResult result = RestResult.ok();
        restResult.setMsg("");
        int error = 0;
        for(FlowChangeDTO dto: list){
            try {
                result = flowChange(dto);
            }catch (Exception e) {
                result.setSuccess(false);
                result.setMsg(e.getMessage());
                error++;
                restResult.setMsg(restResult.getMsg() + result.getMsg());
            }
        }
        if(error == list.size()){
            restResult.setMsg("操作失败," + restResult.getMsg());
            restResult.setCode(ErrorCode.COMMON_ERROR);
            restResult.setSuccess(false);
        } else {
            restResult.setMsg("操作成功,数量：" +list.size()+ restResult.getMsg());
        }
        return restResult;
    }
    /**
     * 批量流程修改
     */
    @PostMapping("/flow_change_batch")
    public final RestResult  flowChangeBatch(@RequestBody @Valid FlowChangeDTO dto) {
        FlowContext flowContext = FlowContextHolder.currentContext();
        String flowKey = dto.getFlowKey();
        String buttonKey = dto.getButtonKey();
        String comment = dto.getComment();
        if (dto.getBusIdList() == null || dto.getBusIdList().size() < 1) {
            return RestResult.error(String.format("缺少参数busIdList"));
        }

        Flow flow = flowAdapter.getFlowService().findByFlowKey(flowKey);
        if (flow == null) {
            return RestResult.error(String.format("流程%s未定义", flowKey));
        }

        if (flow.getFlagDisable()) {
            return RestResult.error(String.format("流程%s已禁用", flowKey));
        }

        List<FlowButton> buttons = flowAdapter.getFlowButtonService(true).getByFlowId(flow.getId());

        Optional<FlowButton> optionalFlowButton = buttons.stream().filter(b -> b.getCode().equalsIgnoreCase(buttonKey)).findFirst();
        if (!optionalFlowButton.isPresent()) {
            return RestResult.error(String.format("流程按钮%s未定义", buttonKey));
        }
        FlowButton button = optionalFlowButton.get();


        flowContext.setFlow(flow);
        flowContext.setButton(button);
        flowContext.setButtons(buttons);
        flowContext.setComment(comment);
        flowContext.setAttachmentUrl(dto.getAttachmentUrl());
        flowContext.setSignBase64(dto.getSignBase64());
        flowContext.setBusTable(dto.getBusTable());
        flowContext.setBusIdName(dto.getBusIdName());
        flowContext.setBusTypeName(dto.getBusTypeName());
        flowContext.setFlowStatusTextTo(dto.getFlowStatusTextTo());
        flowContext.setFlowStatusTextFrom(dto.getFlowStatusTextFrom());
        flowContext.setBusIdList(dto.getBusIdList());

        service.handleFlowChangeBatch();
        String handledMsg = flowContext.getHandledMsg();
        Object handledResult = flowContext.getHandledResult();
        Boolean allError = flowContext.getBusIdErrorList() != null && flowContext.getBusIdErrorList().size() == flowContext.getBusIdList().size();
        FlowContextHolder.clear();
        if (allError) {
            return RestResult.error(handledMsg, handledResult);
        }
        return RestResult.ok(handledMsg, handledResult);
    }
}
